﻿// Sheego.Service.X400
// Copyright(C) 2015 Schwab Versand GmbH
//
// This source file is subject to the Microsoft Public License(Ms-PL).
// http://www.opensource.org/licenses/ms-pl.html
// All other rights reserved.
using Sheego.Service.X400.Job.Shared;
using Sheego.Service.X400.Job.Shared.BO;
using Sheego.Service.X400.Job.Shared.Locator;
using Sheego.Service.X400.Job.Shared.Matcher;
using Sheego.Service.X400.Job.Shared.Processor;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace Sheego.Service.X400.Job.Impl
{
    class XmlWrapper : IXmlWrapper
    {
        private string XmlFilePath;
        private string KeyNameSpace;
        private string UriNameSpace;

        private XmlDocument xmlDocument = null;
        XmlNamespaceManager nsManager = null;
        public XmlWrapper(String xmlFilePath, String keyNameSpace, String uriNameSpace)
        {
            XmlFilePath = xmlFilePath;
            UriNameSpace = uriNameSpace;
            KeyNameSpace = keyNameSpace;
        }

       

        #region IXmlWrapper Members

        public T1 GetElementByXPath<T1>(string xPath)
        {
            if (String.IsNullOrWhiteSpace(xPath))
                throw new ArgumentNullException(xPath);

            var node = xmlDocument.SelectSingleNode(xPath, nsManager);
            if (node == null) 
                throw new KeyNotFoundException(xPath);
            return ConvertNode<T1>(node); 
        }

        public IList<T2> GetElementsByXPath<T2>(string xPath)
        {
            if (String.IsNullOrWhiteSpace(xPath))
                throw new ArgumentNullException(xPath);

            var List = new List<T2>();
            var nodeList = xmlDocument.SelectNodes(xPath,nsManager);
            foreach (XmlNode node in nodeList)
            {
                T2 elm = ConvertNode<T2>(node);
                List.Add(elm);
            }
            return List;
        }

        private T3 ConvertNode<T3>(XmlNode node)
        {
            if (typeof(T3) == typeof(String))
            {
                return (T3)Convert.ChangeType(node.InnerText, typeof(T3)); 
            }

            if (typeof(T3) == typeof(bool))
            {
                return (T3)Convert.ChangeType(node.InnerText, typeof(T3));
            }


            if (typeof(T3) == typeof(IRange))
            {
                var parser = JobLocator.GetRangeParser();
                return (T3)parser.Parse(node.InnerText);
            }

            if (typeof(T3) == typeof(IX400MessageRule))
            {
                var rule = JobLocator.GetMessageRule();
                rule.Matcher = ConvertNode<IX400MessageMatcher>(node["Matcher"]);
                rule.Processor = ConvertNode<IX400MessageProcessor>(node["Processor"]);
                return (T3)rule;
            }


            if (typeof(T3) == typeof(IX400MessageMatcher))
            {
                var Type = node.Attributes["Type"].Value;
                var matcher = JobLocator.GetMessageMatcher(Type);
                foreach (XmlNode property in node.ChildNodes)
                {
                    var Name = property.Attributes["Name"].Value;
                    var Value = property.InnerText;
                    matcher.Config(Name, Value);
                }
                return (T3)matcher;
            }

            if (typeof(T3) == typeof(IX400MessageProcessor))
            {
                var Type = node.Attributes["Type"].Value;
                var processor = JobLocator.GetMessageProcessor(Type);
                foreach (XmlNode property in node.ChildNodes)
                {
                    var Name = property.Attributes["Name"].Value;
                    var Value = property.InnerText;
                    processor.Config(Name, Value);
                }
                return (T3)processor;
            }

            throw new NotImplementedException();

        }

      
      

        public void Update()
        {

            if (!File.Exists(XmlFilePath))
                throw new FileNotFoundException(XmlFilePath);

            xmlDocument = new XmlDocument();
            xmlDocument.Load(XmlFilePath);

            nsManager = new XmlNamespaceManager(xmlDocument.NameTable);
            nsManager.AddNamespace(KeyNameSpace, UriNameSpace);


        }

        #endregion

    }
}
